热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

测向|主设备_nrf52832学习笔记蓝牙从机广播

篇首语:本文由编程笔记#小编为大家整理,主要介绍了nrf52832学习笔记蓝牙从机广播相关的知识,希望对你有一定的参考价值。nrf52832学习笔记

篇首语:本文由编程笔记#小编为大家整理,主要介绍了nrf52832 学习笔记蓝牙从机广播相关的知识,希望对你有一定的参考价值。



nrf52832 学习笔记(三)蓝牙从机广播

蓝牙从机要想被主机连接,首先需要发送广播信息,周围主机通过扫描广播信号,根据从机的广播信息,判断是否连接。


蓝牙协议栈初始化

不管是主机还是从机,要想使用蓝牙功能,都需要对蓝牙协议栈进行初始化操作

/**@brief Function for initializing the BLE stack.
*
* @details Initializes the SoftDevice and the BLE event interrupt.
*/

static void ble_stack_init(void)

ret_code_t err_code;
// 1.协议栈低速时钟初始化并注册状态观察者函数
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// 2.使用默认配置配置蓝牙协议栈
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// 3.使能协议栈
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// 4.注册蓝牙事件观察者回调函数
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

蓝牙协议栈初始化做了四件事:


  • 协议栈时钟低速初始化并注册状态观察者函数



    协议栈运行除了主时钟外还需要一个低速时钟,低速时钟有三种来源,根据功耗和硬件选择合适的时钟源。


    // <0&#61;> NRF_CLOCK_LF_SRC_RC //内部RC时钟&#xff0c;比外部低速晶振耗电多10ua左右
    // <1&#61;> NRF_CLOCK_LF_SRC_XTAL //外部低速晶振&#xff0c;最省电但是需要外接低速晶振
    // <2&#61;> NRF_CLOCK_LF_SRC_SYNTH //内部主时钟产生的低速时钟&#xff0c;最耗电
    #ifndef NRF_SDH_CLOCK_LF_SRC
    #define NRF_SDH_CLOCK_LF_SRC 1
    #endif
    nrf_clock_lf_cfg_t const clock_lf_cfg &#61;

    .source &#61; NRF_SDH_CLOCK_LF_SRC,
    .rc_ctiv &#61; NRF_SDH_CLOCK_LF_RC_CTIV,
    .rc_temp_ctiv &#61; NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
    .accuracy &#61; NRF_SDH_CLOCK_LF_ACCURACY //时钟准确度
    ;


    注册的状态观察者函数其实就是一个中断服务函数的子函数&#xff0c;用户根据返回的状态信息做出相应处理。比如蓝牙协议栈使能失败&#xff0c;协议栈会触发一个软中断&#xff0c;软中断中调用注册的状态观察者函数&#xff0c;用户在状态观察者函数中根据状态信息点灯或者干别的事情&#xff0c;方便用户观察协议栈的运行状态。


  • 使用默认配置配置蓝牙协议栈



    默认配置信息可以在sdk_config.h中根据自己需要自行修改。


    // 空中包长度 &#61; NRF_SDH_BLE_GATT_MAX_MTU_SIZE &#43; 4&#xff0c;提高蓝牙传输速率时&#xff0c;可以修改这里
    #ifndef NRF_SDH_BLE_GAP_DATA_LENGTH
    #define NRF_SDH_BLE_GAP_DATA_LENGTH 27
    #endif
    // 从机角色个数&#xff0c;可以连接 ? 个主机
    #ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT
    #define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1
    #endif
    // 主机角色个数&#xff0c;可以连接 ? 个从机
    #ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT
    #define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0
    #endif
    // 主机&#43;从机 总的角色个数
    #ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT
    #define NRF_SDH_BLE_TOTAL_LINK_COUNT 1
    #endif
    // 一个连接间隔内可以用于数据传输的事件长度&#xff0c;以1.25 ms为单位。
    // 提高蓝牙传输速率时&#xff0c;可以修改这里和连接事件长度扩展相配合
    #ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 6
    #endif
    // MTU最大长度 蓝牙4.0 最大23 蓝牙4.2以上最大247
    #ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 23
    #endif
    // NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4.
    #ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE
    #define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408
    #endif
    // NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs.
    // 主要每增加一个UUIDs 协议栈消耗RAM会增加0x10
    #ifndef NRF_SDH_BLE_VS_UUID_COUNT
    #define NRF_SDH_BLE_VS_UUID_COUNT 10
    #endif
    // NRF_SDH_BLE_SERVICE_CHANGED - Include the Service Changed characteristic in the Attribute Table.
    #ifndef NRF_SDH_BLE_SERVICE_CHANGED
    #define NRF_SDH_BLE_SERVICE_CHANGED 0
    #endif

  • 使能协议栈

  • 注册蓝牙事件观察者回调函数


GAP初始化

Generic Access Profile(通用访问协议)也就是常说的GAP&#xff0c;所有蓝牙设备中必须存在的profile。NRF52832 SDK中对GAP的操作均在 ble_gap.h中。


GAP 安全模式

蓝牙配对时输入密码功能是GAP的一部分&#xff0c;当然也可以选择开放模式&#xff08;不用输入密码&#xff09;则不用进行这里的静态密匙设置操作

/**&#64;brief GAP connection security modes.
*
* Security Mode 0 Level 0: No access permissions at all (this level is not defined by the Bluetooth Core specification).\\n
* Security Mode 1 Level 1: No security is needed (aka open link).\\n
* Security Mode 1 Level 2: Encrypted link required, MITM protection not necessary.\\n
* Security Mode 1 Level 3: MITM protected encrypted link required.\\n
* Security Mode 1 Level 4: LESC MITM protected encrypted link using a 128-bit strength encryption key required.\\n
* Security Mode 2 Level 1: Signing or encryption required, MITM protection not necessary.\\n
* Security Mode 2 Level 2: MITM protected signing required, unless link is MITM protected encrypted.\\n
*/

typedef struct

uint8_t sm : 4; /**
uint8_t lv : 4; /**
ble_gap_conn_sec_mode_t;
//设置静态钥匙
#define STATIC_PASSKEY "123456"
static ble_opt_t m_static_pin_option;
uint8_t passkey[] &#61; STATIC_PASSKEY;
m_static_pin_option.gap_opt.passkey.p_passkey &#61; passkey;
err_code &#61; sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &m_static_pin_option);

GAP MAC地址设置

蓝牙的MAC地址分为两类


  • Public

    需要申请购买, 24bit&#xff08;MSB&#xff09;公司ID &#43; 24bit设备地址


  • Random

    随机地址分为两种



    • 静态随机地址

      随机生成的&#xff0c;其中MSB最高两位必须为 11


    • 私有随机地址
      • Non-Resolvable

        不解析私有地址&#xff0c;MSB最高两位必须为 00&#xff0c;隔一段时间会自动变化一次


      • Resolvable

        解析私有地址&#xff0c; MSB最高两位必须为 01&#xff0c; 由24bit&#xff08;MSB&#xff09;随机数 &#43; 24bit hash组成


一般静态随机地址比较常用&#xff0c;可以通过 sd_ble_gap_addr_set 函数在广播开始前设置蓝牙MAC地址。

ble_gap_addr_t gap_addr &#61;

.addr_type &#61; BLE_GAP_ADDR_TYPE_PUBLIC,
.addr &#61; 0x00, 0x11, 0x00, 0xE9, 0x81, 0xC9
;
sd_ble_gap_addr_set(&gap_addr);

GAP 蓝牙设备名称

GAP中包含了蓝牙的名称&#xff0c;但是蓝牙名称信息是通过广播包传递给周围设备的&#xff0c;因此想要其他设备可以获取自己的蓝牙名称&#xff0c;需要在广播初始化时向广播包中添加蓝牙名称信息。

#define DEVICE_NAME "Nordic_Blinky"
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
sd_ble_gap_device_name_set(&sec_mode,(const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME));

注意大多数手机使用的是UTF-8编码格式&#xff0c;因此想要手机上显示中文蓝牙设备名&#xff0c;需要修改MDK文件编码格式为UTF-8


GAP 蓝牙图标

GAP中包含了蓝牙的图标信息&#xff0c;但是蓝牙图标信息也是通过广播包传递给周围设备的&#xff0c;因此想要其他设备可以获取对应的蓝牙图标&#xff0c;需要在广播初始化时向广播包中添加蓝牙图标信息。

/** &#64;defgroup BLE_APPEARANCES Bluetooth Appearance values
* &#64;note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u&#61;org.bluetooth.characteristic.gap.appearance.xml
* &#64; */

#define BLE_APPEARANCE_UNKNOWN 0 /**
#define BLE_APPEARANCE_GENERIC_PHONE 64 /**
#define BLE_APPEARANCE_GENERIC_COMPUTER 128 /**
#define BLE_APPEARANCE_GENERIC_WATCH 192 /**
#define BLE_APPEARANCE_WATCH_SPORTS_WATCH 193 /**
#define BLE_APPEARANCE_GENERIC_CLOCK 256 /**
#define BLE_APPEARANCE_GENERIC_DISPLAY 320 /**
#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 384 /**
#define BLE_APPEARANCE_GENERIC_EYE_GLASSES 448 /**
#define BLE_APPEARANCE_GENERIC_TAG 512 /**
#define BLE_APPEARANCE_GENERIC_KEYRING 576 /**
#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 640 /**
#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 704 /**
#define BLE_APPEARANCE_GENERIC_THERMOMETER 768 /**
#define BLE_APPEARANCE_THERMOMETER_EAR 769 /**
#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR 832 /**
#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 /**
#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 896 /**
#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM 897 /**
#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 898 /**
#define BLE_APPEARANCE_GENERIC_HID 960 /**
#define BLE_APPEARANCE_HID_KEYBOARD 961 /**
#define BLE_APPEARANCE_HID_MOUSE 962 /**
#define BLE_APPEARANCE_HID_JOYSTICK 963 /**
#define BLE_APPEARANCE_HID_GAMEPAD 964 /**
#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE 965 /**
#define BLE_APPEARANCE_HID_CARD_READER 966 /**
#define BLE_APPEARANCE_HID_DIGITAL_PEN 967 /**
#define BLE_APPEARANCE_HID_BARCODE 968 /**
#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER 1024 /**
#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR 1088 /**
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 /**
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 /**
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP 1091 /**
#define BLE_APPEARANCE_GENERIC_CYCLING 1152 /**
#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER 1153 /**
#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR 1154 /**
#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR 1155 /**
#define BLE_APPEARANCE_CYCLING_POWER_SENSOR 1156 /**
#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR 1157 /**
#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 3136 /**
#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 3137 /**
#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN 3138 /**
#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE 3200 /**
#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT 5184 /**
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 /**
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 /**
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 /**
//设置图标信息
sd_ble_gap_appearance_set(uint16_t appearance);


GAP 连接参数

BLE功耗低的原因之一就是仅在数据收发时开启射频电路&#xff0c;这里有一个重要的参数----连接间隔 connection interval&#xff0c;它约定了BLE双方碰头时间&#xff0c;当主从机配对连接后&#xff0c;每隔一段时间&#xff0c;主机会向从机发送一包数据&#xff0c;从机接到主机数据后发一包数据给主机&#xff0c;用与主从机之间数据交换和连接状态判断&#xff08;没有数据包会发生连接超时&#xff0c;断开连接&#xff09;。当然连接间隔是可以根据需要灵活修改的&#xff08;7.5ms – 4000ms&#xff09;

#define MIN_CONN_INTERVAL MSEC_TO_UNITS(100, UNIT_1_25_MS) /**
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(200, UNIT_1_25_MS) /**
#define SLAVE_LATENCY 0 /**
#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**
/**&#64;brief Function for the GAP initialization.
*
* &#64;details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
* device including the device name, appearance, and the preferred connection parameters.
*/

static void gap_params_init(void)

ret_code_t err_code;
ble_gap_conn_params_t gap_conn_params;
memset(&gap_conn_params, 0, sizeof(gap_conn_params));
gap_conn_params.min_conn_interval &#61; MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval &#61; MAX_CONN_INTERVAL;
gap_conn_params.slave_latency &#61; SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout &#61; CONN_SUP_TIMEOUT;
err_code &#61; sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);


连接参数解释
最小连接间隔范围 7.5ms - 4000ms 蓝牙连接后每隔一段时间唤醒一次射频模块进行主从机通信&#xff0c;连接间隔越长则越省电但是数据传输延迟和传输速率会越小
最大连接间隔当没有数据时&#xff0c;主从机为了省电使用最大连接间隔 发生空数据包保持连接状态
潜伏周期从机可以跳过连接数据包的次数。当潜伏周期为3时&#xff0c;如果从机没有数据需要发送则从机可以跳过三次连接数据包&#xff08;不应答主机&#xff09;&#xff0c;从而降低从机功耗。
超时时间超过超时时间还没有接收到蓝牙数据包&#xff0c;会产生超时事件&#xff0c;可以在超时事件中断开蓝牙连接。范围 100ms - 32000ms。 超时时间 >&#61; 连接间隔 * &#xff08; 潜伏周期 &#43; 1&#xff09;

其中图中M为主机发送的数据包&#xff0c; S为从机发送的数据包&#xff0c;当潜伏周期为0时&#xff0c;每个主机数据包从机均需要应答&#xff0c;而当潜伏周期为3时&#xff0c;从机可以跳过三个数据包应答一次主机。


GAP 发射功率

nrf52832 支持-40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, &#43;3dBm , &#43;4dBm.9种功率,通过sd_ble_gap_tx_power_set 函数进行设置.

/**&#64;brief GAP TX Power roles.
*/

enum BLE_GAP_TX_POWER_ROLES

BLE_GAP_TX_POWER_ROLE_ADV &#61; 1, /**<广播角色. */
BLE_GAP_TX_POWER_ROLE_SCAN_INIT &#61; 2, /**<扫描和发起者角色. */
BLE_GAP_TX_POWER_ROLE_CONN &#61; 3, /**<连接角色. */
;
/**&#64;brief Set the radio&#39;s transmit power.
*
* &#64;param[in] role The role to set the transmit power for, see &#64;ref BLE_GAP_TX_POWER_ROLES for
* possible roles.
* &#64;param[in] handle The handle parameter is interpreted depending on role:
* - If role is &#64;ref BLE_GAP_TX_POWER_ROLE_CONN, this value is the specific connection handle.
* - If role is &#64;ref BLE_GAP_TX_POWER_ROLE_ADV, the advertising set identified with the advertising handle,
* will use the specified transmit power, and include it in the advertising packet headers if
* &#64;ref ble_gap_adv_properties_t::include_tx_power set.
* - For all other roles handle is ignored.
* &#64;param[in] tx_power Radio transmit power in dBm (see note for accepted values).
*
* &#64;note Supported tx_power values: -40dBm, -20dBm, -16dBm, -12dBm, -8dBm, -4dBm, 0dBm, &#43;3dBm and &#43;4dBm.
* &#64;note The initiator will have the same transmit power as the scanner.
* &#64;note When a connection is created it will inherit the transmit power from the initiator or
* advertiser leading to the connection.
*
* &#64;retval ::NRF_SUCCESS Successfully changed the transmit power.
* &#64;retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* &#64;retval ::BLE_ERROR_INVALID_ADV_HANDLE Advertising handle not found.
* &#64;retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied.
*/

SVCALL(SD_BLE_GAP_TX_POWER_SET, uint32_t, sd_ble_gap_tx_power_set(uint8_t role, uint16_t handle, int8_t tx_power));

连接参数初始化

在NRF52832协议栈中&#xff0c;当主从机连接后&#xff0c;如果想要修改GAP连接参数&#xff0c;需要从机向主机发起连接参数更新请求&#xff08;从机发起连接参数请求前&#xff0c;使用主机的连接参数&#xff09;&#xff0c;主机收到连接参数更新请求后&#xff0c;如果同意更新GAP参数则会更改自身GAP参数然后向从机发送同意连接参数更新。从机是何时发起连接参数更新请求&#xff1f;

ret_code_t ble_conn_params_init(const ble_conn_params_init_t * p_init)

ret_code_t err_code;
VERIFY_PARAM_NOT_NULL(p_init);
m_conn_params_config &#61; *p_init;
m_conn_params_config.p_conn_params &#61; &m_preferred_conn_params;
if (p_init->p_conn_params !&#61; NULL)

// Set the connection params in stack.
err_code &#61; sd_ble_gap_ppcp_set(p_init->p_conn_params);
if (err_code !&#61; NRF_SUCCESS)

return err_code;

m_preferred_conn_params &#61; *p_init->p_conn_params;

else

// Get the (default) connection params from stack.
err_code &#61; sd_ble_gap_ppcp_get(&m_preferred_conn_params);
if (err_code !&#61; NRF_SUCCESS)

return err_code;


//lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_INSTANCE_COUNT is 0
for (uint32_t i &#61; 0; i < NRF_BLE_CONN_PARAMS_INSTANCE_COUNT; i&#43;&#43;)

ble_conn_params_instance_t * p_instance &#61; &m_conn_params_instances[i];
instance_free(p_instance);
p_instance->timer_id &#61; &m_timer_data[i];
err_code &#61; app_timer_create(&p_instance->timer_id,
APP_TIMER_MODE_SINGLE_SHOT,
update_timeout_handler);
if (err_code !&#61; NRF_SUCCESS)

return NRF_ERROR_INTERNAL;


//lint -restore
return NRF_SUCCESS;

/**&#64;brief Function for initializing the Connection Parameters module.
*/

static void conn_params_init(void)

ret_code_t err_code;
ble_conn_params_init_t cp_init;
memset(&cp_init, 0, sizeof(cp_init));
cp_init.p_conn_params &#61; NULL;
cp_init.first_conn_params_update_delay &#61; FIRST_CONN_PARAMS_UPDATE_DELAY; //主从机连接后&#xff0c;延时多长时间进行第一次参数更新请求
cp_init.next_conn_params_update_delay &#61; NEXT_CONN_PARAMS_UPDATE_DELAY; //延时多长时间进行第二次参数更新请求
cp_init.max_conn_params_update_count &#61; MAX_CONN_PARAMS_UPDATE_COUNT; //最大尝试更新次数
cp_init.start_on_notify_cccd_handle &#61; BLE_GATT_HANDLE_INVALID; //GAP 通知服务句柄
cp_init.disconnect_on_fail &#61; false; //更新不成功自动断开连接&#xff1f;
cp_init.evt_handler &#61; on_conn_params_evt;
cp_init.error_handler &#61; conn_params_error_handler;
err_code &#61; ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);

ble_conn_params_init 函数其实就是创建了几个软件定时器&#xff0c;在软件定时器超时回调函数 update_timeout_handler 中发送参数更新请求。ble_conn_params.c中注册了一个观察者回调函数&#xff0c;当主从机连接成功后&#xff0c;会在 on_connect(p_ble_evt); 函数中开启参数更新软件定时器。

/**
* &#64;brief Function for handling BLE events.
*
* &#64;param[in] p_ble_evt Event received from the BLE stack.
* &#64;param[in] p_context Context.
*/

static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)

switch (p_ble_evt->header.evt_id)

case BLE_GAP_EVT_CONNECTED:
on_connect(p_ble_evt);
break;
case BLE_GAP_EVT_DISCONNECTED:
on_disconnect(p_ble_evt);
break;
case BLE_GATTS_EVT_WRITE:
on_write(p_ble_evt);
break;
case BLE_GAP_EVT_CONN_PARAM_UPDATE:
on_conn_params_update(p_ble_evt);
break;
default:
// No implementation needed.
break;



GATT 初始化

nrf52832中对GATT初始化主要是为了初始化MTU长度。



MTU: 最大传

推荐阅读
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
author-avatar
天之道
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有